package com.UdpRecieve.Netty.server.handler;

import com.UdpRecieve.framework.ExceptionBusiness.BusinessIoException;
import com.UdpRecieve.Netty.codec.Codec;
import com.UdpRecieve.Netty.util.*;
import com.UdpRecieve.secret.service.SecretBusinessLogicInterface;
import com.UdpRecieve.secret.SecretBusinessLogicFactory;
import com.UdpRecieve.tool.Global;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;


public class FileReceiveServerHandler extends ChannelInboundHandlerAdapter {

	static ConcurrentHashMap<String, FileBlockClass> connectBlockList = new ConcurrentHashMap<String,FileBlockClass>();

	private FileBlockClass fileBlockClass;

	private Long readLength;

	private String channelId;

	private String company = Global.getConfig("secret.name");//公司名

	private String location = Global.getConfig("location");//秘网/外网

	private SecretBusinessLogicInterface filePigeonholeSave = new SecretBusinessLogicFactory(company,location).INSTANCE();//初始化密标逻辑块工厂

	Logger logger = LoggerFactory.getLogger(FileReceiveServerHandler.class);

	/**
	 * 判断是否是文件块,接受并写入文件
	 * 当文件块全部落地,执行审批和密标业务逻辑
	 * @param ctx
	 * @param msg
	 */
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		channelId = ctx.channel().id().asLongText();//获取通道id
		ByteBuf byteBuf = (ByteBuf) msg;
		int type = byteBuf.getInt(0);
		if (type != Codec.TYPE){
			fileBlockClass = connectBlockList.get(channelId);//从队列里获取文件块对象
			readLength = fileBlockClass.getReadLength();//从队列里获取文件总长度
			readLength += byteBuf.readableBytes();
			//更新文件队列中 对应文件块 当前文件读取了的长度
			fileBlockClass.setReadLength(readLength);
			connectBlockList.put(channelId,fileBlockClass);
			//TODO 把文件块写入文件
			try {
				writeToFile(byteBuf);
			} catch (IOException e) {
				logger.info("文件写入文件块异常");
				e.printStackTrace();
			}catch (NullPointerException e){
				logger.info("fileBlockClass为:"+fileBlockClass);
				e.printStackTrace();
			}

			try {
				if(readLength >= fileBlockClass.getFileLength()){
					fileBlockClass.setFileLength(0);//初始化文件总长度
					fileBlockClass.getOutputStream().close();//关闭流
					ctx.pipeline().addLast("length",new LengthFieldBasedFrameDecoder(65535,5,4,0,0));
					System.out.println("添加length的handler");
					//TODO 执行密标业务相关逻辑
					filePigeonholeSave.saveFile(fileBlockClass.getFilePigeonhole(),"成功");
				}
			}catch (BusinessIoException e){
				e.printStackTrace();
				logger.info("业务流程异常");
				filePigeonholeSave.saveFile(fileBlockClass.getFilePigeonhole(),"失败");
			} catch (IOException e) {
				logger.info("文件块流关闭异常：fileBlockClass.getOutputStream().close()");
				e.printStackTrace();
			}catch (NullPointerException e){
				e.printStackTrace();
			}
		} else {
			try {
				super.channelRead(ctx, msg);
			} catch (Exception e) {
				logger.info("super.channelRead(ctx, msg)异常");
				e.printStackTrace();
			}
		}
	}

	/**
	 * 把文件块写入文件
	 * @param byteBuf
	 * @throws IOException
	 */
	private void writeToFile(ByteBuf byteBuf) throws IOException {
		byte[] bytes = new byte[byteBuf.readableBytes()];
		byteBuf.readBytes(bytes);
		fileBlockClass.getOutputStream().write(bytes);
		byteBuf.release();
	}

}
